package com.yinhai.message.implement.wx.sender;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yinhai.core.app.api.util.ServiceLocator;
import com.yinhai.core.common.api.config.impl.SysConfig;
import com.yinhai.core.common.api.util.ValidateUtil;
import com.yinhai.message.api.bean.TMMessage;
import com.yinhai.message.api.bean.TMUser;
import com.yinhai.message.api.bean.TMWeChat;
import com.yinhai.message.api.exception.TMException;
import com.yinhai.message.api.util.WxMessageType;
import com.yinhai.message.api.vo.TMMessageVo;
import com.yinhai.message.core.bpo.IMessageBpo;
import com.yinhai.message.core.po.MessageFilePo;
import com.yinhai.message.core.sender.IMessageSender;
import com.yinhai.message.core.util.FTPUtils;
import com.yinhai.message.core.util.IMessageConstant;
import com.yinhai.message.implement.wx.tool.WxHttpsSendUtil;

/**
 * 
 * @author yanglq
 * 2017.4.6
 */
@Service
public class WechatMessageSender implements IMessageSender<TMMessageVo>{
	
	@Override
	public List<TMUser> sendMessage(TMMessageVo vo) {
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		try {
			TMWeChat wx = vo.getWechat(); 
			TMMessage msg = vo.getMessage();
			String accessToken = wx.getAccessToken();
			if (ValidateUtil.isEmpty(accessToken)) {
				accessToken = wxHttps.getAccessToken(wx.getAppid(),wx.getSecret());
			}
			if (msg.isToAlluser()) {
				sendToAllUser(vo, accessToken);
			} else if (msg.getUserSign().equals("openId")) {
				return sendWithOpenID(vo, accessToken);
			} else if (msg.getUserSign().equals("UnionId")) {
				return sendWithUnionID(vo, accessToken);
			}
		} catch (Exception ex) {
			throw new TMException("send exception--"+ex.getMessage());
		}
		return vo.getUserlist();
	}	
	/**
	 * 上传临时素材
	 * @param access_token
	 * @param po
	 * @param msgtype
	 * @return
	 * @throws Exception
	 */
	String uploadFile(String access_token,MessageFilePo po,String msgtype,String mimetype) throws Exception{
		String media_id = null;
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		String storeMode = po.getFilestoremode();
		InputStream ins = null;
		if (IMessageConstant.MSG_FILE_STORE_LOCAL.equals(storeMode)) {
			String realpath = po.getFilepath();
			File file = new File(realpath);
			media_id = wxHttps.uploadFile(access_token, file, msgtype, mimetype, po.getFilename());
		} else if (IMessageConstant.MSG_FILE_STORE_FTPSERVER.equals(storeMode)) {
			FTPUtils ftpUtils = FTPUtils.getInstance();
			String serverName = SysConfig.getSysConfig("msgFileStorePlace");
			ins = ftpUtils.retrieveFile(serverName, po.getFilepath(), new String(po.getFilename().getBytes("GBK"),"iso-8859-1"));
			media_id = wxHttps.uploadFile(access_token, ins, msgtype, mimetype, po.getFilename());
		} else if (IMessageConstant.MSG_FILE_STORE_UNIFIED_STORE.equals(storeMode)) {

		}
		return media_id;
	}
	/**
	 * 消息附件 上传 到微信临时素材
	 * @param accessToken
	 * @param mgid
	 * @param msgtype
	 * @return
	 * @throws Exception
	 */
	List<String> getMediaIds(String accessToken,String mgid,String msgtype) throws Exception{
		//查询附件
		IMessageBpo messageBpo = (IMessageBpo) ServiceLocator.getService("messageBpo");
		List<MessageFilePo> listPo = messageBpo.queryMessageFileByMsgid(mgid);
		List<String> media_ids = new ArrayList<>();
		if(WxMessageType.IMAGE.equals(msgtype)){
			for(MessageFilePo po :listPo){
				Path path = Paths.get(po.getFilename());
				String mimetype = Files.probeContentType(path);
				if (mimetype.startsWith("image/")) {
					media_ids.add(uploadFile(accessToken, po, msgtype, mimetype));
				}
			}
		}else if (WxMessageType.VIDEO.equals(msgtype)){
			for(MessageFilePo po :listPo){
				Path path = Paths.get(po.getFilename());
				String mimetype = Files.probeContentType(path);
				if (mimetype.startsWith("video/")) {
					media_ids.add(uploadFile(accessToken, po, msgtype, mimetype));
				}
			}
		}else if (WxMessageType.VOICE.equals(msgtype)){
			for(MessageFilePo po :listPo){
				Path path = Paths.get(po.getFilename());
				String mimetype = Files.probeContentType(path);
				if (mimetype.startsWith("audio/")) {
					media_ids.add(uploadFile(accessToken, po, msgtype, mimetype));
				}
			}
		}
		return media_ids;
	}
	/**
	 * 消息附件 上传 到微信临时素材 未指定 消息类型
	 * @param accessToken
	 * @param mgid
	 * @return
	 */
	List<Map<String,String>> getMediaIdsAndType(String accessToken,String mgid) throws Exception{
		List<Map<String,String>> list = new ArrayList<>();
		//查询附件
		IMessageBpo messageBpo = (IMessageBpo) ServiceLocator.getService("messageBpo");
		List<MessageFilePo> listPo = messageBpo.queryMessageFileByMsgid(mgid);
		for(MessageFilePo po :listPo){
			Map<String,String> map = new HashMap<>();
			Path path = Paths.get(po.getFilename());
			String mimetype = Files.probeContentType(path);
			if (mimetype.startsWith("image/")) {
				String media_id = uploadFile(accessToken, po, "image", mimetype);
				map.put("media_id", media_id);
				map.put("msgtype", "image");
			} else if (mimetype.startsWith("video/")) {
				String media_id = uploadFile(accessToken, po, "video", mimetype);
				map.put("media_id", media_id);
				map.put("msgtype", "video");
			} else if (mimetype.startsWith("audio/")) {
				String media_id = uploadFile(accessToken, po, "voice", mimetype);
				map.put("media_id", media_id);
				map.put("msgtype", "voice");
			}
			list.add(map);
		}
		return list;
	}
	
	//jsonStr
	String getTextJsonStr(String openId, String text){
		StringBuilder strJson = new StringBuilder();
		strJson.append("{\"touser\" :\"")
		   .append(openId)
		   .append("\",\"msgtype\":\"text\",")
		   .append("\"text\":{\"content\":\"")
		   .append(text)
		   .append("\"}}");
		return strJson.toString();
	}
	String getMediaJsonStr(String openId, String msgtype, String media_id){
		StringBuilder strJson = new StringBuilder();
		strJson.append("{\"touser\" :\"")
		   .append(openId)
		   .append("\",\"msgtype\":\"")
		   .append(msgtype)
		   .append("\",\"")
		   .append(msgtype)
		   .append("\":{\"media_id\":\"")
		   .append(media_id)
		   .append("\"}}");
		return strJson.toString();
	}

	//jsonData
	String getJsonStrByJsonData(String openId,String jsonData){
		StringBuilder strJson = new StringBuilder();
		strJson.append("{\"touser\" :\"")
		   .append(openId)
		   .append("\",")
		   .append(jsonData)
		   .append("}");
		return strJson.toString();
	}
	String getNewsJsonData(String url,String picurl,String title,String description){
		StringBuilder strJson = new StringBuilder();
		strJson.append("\"msgtype\":\"news\",")
		   .append("\"news\":{\"articles\": [ {\"title\":\"")
		   .append(title)
		   .append("\",\"description\":\"")
		   .append(description)
		   .append("\",\"url\":\"")
		   .append(url)
		   .append("\",\"picurl\":\"")
		   .append(picurl)
		   .append("\"}]}");
		return strJson.toString();
	}
	String getTextJsonData(String text){
		StringBuilder strJson = new StringBuilder();
		strJson.append("\"msgtype\":\"text\",")
		   .append("\"text\":{\"content\":\"")
		   .append(text)
		   .append("\"}");
		return strJson.toString();
	}
	String getMediaJsonData( String msgtype, String media_id){
		StringBuilder strJson = new StringBuilder();
		strJson.append("\"msgtype\":\"")
		   .append(msgtype)
		   .append("\",\"")
		   .append(msgtype)
		   .append("\":{\"media_id\":\"")
		   .append(media_id)
		   .append("\"}");
		return strJson.toString();
	}
	
	void sendToAllUser(TMMessageVo vo,String accessToken)throws Exception{
		TMMessage msg = vo.getMessage();
		String msgtype = msg.getMsgtype();
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		Set<String> openIds=wxHttps.getUsers(accessToken,"",0);
		if(ValidateUtil.isEmpty(msgtype)){
			String jsonData = msg.getJsonData();
			List<Map<String,String>> media_ids = getMediaIdsAndType(accessToken, msg.getMgid());
			for(String openId:openIds){
				String strJson = getTextJsonStr(openId,msg.getText());
				wxHttps.postMessage(accessToken, strJson, "application/json");
				for(Map<String,String> map :media_ids){
					String strJson1 = getMediaJsonStr(openId, map.get("msgtype"), map.get("media_id"));
					wxHttps.postMessage(accessToken, strJson1, "application/json");
				}
				if(ValidateUtil.isNotEmpty(jsonData)){
					String strJson2 = getJsonStrByJsonData(openId, jsonData);
					wxHttps.postMessage(accessToken, strJson2, "application/json");
				}
			}
		}else if(WxMessageType.TEXT.equals(msgtype)){
			for(String openId:openIds){
				String strJson = getTextJsonStr(openId,msg.getText());
				wxHttps.postMessage(accessToken, strJson, "application/json");
			}
		}else if(WxMessageType.IMAGE.equals(msgtype) ||
				 WxMessageType.VOICE.equals(msgtype) ||
				 WxMessageType.VIDEO.equals(msgtype)){
			List<String> media_ids = getMediaIds(accessToken, msg.getMgid(), msgtype);
			for(String openId:openIds){
				for(String media_id:media_ids){
					String strJson = getMediaJsonStr(openId, msgtype, media_id);
					wxHttps.postMessage(accessToken, strJson, "application/json");
				}
			}
		}else if(WxMessageType.NEWS.equals(msgtype)){
			String jsonData = msg.getJsonData();
			if(ValidateUtil.isEmpty(jsonData)){
				jsonData = getNewsJsonData(msg.getUrl(),msg.getPicurl(),msg.getTitle(),msg.getDescription());
			}
			for(String openId:openIds){
				String strJson = getJsonStrByJsonData(openId, jsonData);
				wxHttps.postMessage(accessToken, strJson, "application/json");
			}
			
		}else if(WxMessageType.MUSIC.equals(msgtype)){
			String jsonData = msg.getJsonData();
			for(String openId:openIds){
				String strJson = getJsonStrByJsonData(openId, jsonData);
				wxHttps.postMessage(accessToken, strJson, "application/json");
			}
		}else if(WxMessageType.WXCARD.equals(msgtype)){
			String jsonData = msg.getJsonData();
			for(String openId:openIds){
				String strJson = getJsonStrByJsonData(openId, jsonData);
				wxHttps.postMessage(accessToken, strJson, "application/json");
			}
		}
	}
	List<TMUser> sendWithOpenID(TMMessageVo vo,String accessToken)throws Exception{
		TMMessage msg = vo.getMessage();
		String msgtype = msg.getMsgtype();
		List<TMUser> userList = vo.getUserlist();
		List<TMUser> resultUserList = new ArrayList<>();
		
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		Set<String> openIds=wxHttps.getUsers(accessToken,"",0);
		if(ValidateUtil.isEmpty(msgtype)){
			String jsonData = msg.getJsonData();
			List<Map<String,String>> media_ids = getMediaIdsAndType(accessToken, msg.getMgid());
			for(TMUser user:userList){
				TMUser exuser = new TMUser();
				exuser.setAppId(user.getAppId());
				exuser.setUserId(user.getUserId());
				exuser.setSendSign(user.getSendSign());
				for(String openId:openIds){
					if(openId.equals(user.getWeChat())){
						exuser.setWeChat(openId);
						String strJson = getTextJsonStr(openId,msg.getText());
						try{
							wxHttps.postMessage(accessToken, strJson, "application/json");
						}catch(Exception e){
							exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
							exuser.setErrorInfo(e.getMessage());
						}
						for(Map<String,String> map :media_ids){
							String strJson1 = getMediaJsonStr(openId, map.get("msgtype"), map.get("media_id"));
							try{
								wxHttps.postMessage(accessToken, strJson1, "application/json");
							}catch(Exception e){
								exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
								exuser.setErrorInfo(e.getMessage());
							}
						}
						if(ValidateUtil.isNotEmpty(jsonData)){
							String strJson2 = getJsonStrByJsonData(openId, jsonData);
							try{
								wxHttps.postMessage(accessToken, strJson2, "application/json");
							}catch(Exception e){
								exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
								exuser.setErrorInfo(e.getMessage());
							}
						}
					}
				}
				if(ValidateUtil.isEmpty(exuser.getWeChat())){
					exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
					exuser.setErrorInfo("该人员的 openID 与 微信公众号对应不上");
				}
				resultUserList.add(exuser);
			}
		}else if(WxMessageType.TEXT.equals(msgtype)){
			String jsonData = getTextJsonData(msg.getText());
			resultUserList = sendByJsonData(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.IMAGE.equals(msgtype) ||
				 WxMessageType.VOICE.equals(msgtype) ||
				 WxMessageType.VIDEO.equals(msgtype)){
			List<String> media_ids = getMediaIds(accessToken, msg.getMgid(), msgtype);
			for(String media_id:media_ids){
				String jsonData = getMediaJsonData(msgtype, media_id);
				resultUserList = sendByJsonData(userList, openIds, accessToken, jsonData);
			}
		}else if(WxMessageType.NEWS.equals(msgtype)){
			String jsonData = msg.getJsonData();
			if(ValidateUtil.isEmpty(jsonData)){
				jsonData = getNewsJsonData(msg.getUrl(),msg.getPicurl(),msg.getTitle(),msg.getDescription());
			}
			resultUserList = sendByJsonData(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.MUSIC.equals(msgtype)){
			String jsonData = msg.getJsonData();
			resultUserList = sendByJsonData(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.WXCARD.equals(msgtype)){
			String jsonData = msg.getJsonData();
			resultUserList = sendByJsonData(userList, openIds, accessToken, jsonData);
		}
		return resultUserList;
	}
	List<TMUser> sendWithUnionID(TMMessageVo vo,String accessToken)throws Exception{
		TMMessage msg = vo.getMessage();
		String msgtype = msg.getMsgtype();
		List<TMUser> userList = vo.getUserlist();
		List<TMUser> resultUserList = new ArrayList<>();
		
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		Set<String> openIds=wxHttps.getUsers(accessToken,"",0);
		if(ValidateUtil.isEmpty(msgtype)){
			List<Map<String,String>> media_ids = getMediaIdsAndType(accessToken, msg.getMgid());
			for(TMUser user:userList){
				TMUser exuser = new TMUser();
				exuser.setAppId(user.getAppId());
				exuser.setUserId(user.getUserId());
				exuser.setSendSign(user.getSendSign());
				for(String openId:openIds){
					JSONObject userinfo =JSON.parseObject(wxHttps.getUserInfo(accessToken, openId));
					if(userinfo.getString("UnionID")!=null && userinfo.getString("UnionID").equals(user.getWeChat())){
						exuser.setWeChat(openId);
						String strJson = getTextJsonStr(openId,msg.getText());
						try{
							wxHttps.postMessage(accessToken, strJson, "application/json");
						}catch(Exception e){
							exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
							exuser.setErrorInfo(e.getMessage());
						}
						for(Map<String,String> map :media_ids){
							String strJson1 = getMediaJsonStr(openId, map.get("msgtype"), map.get("media_id"));
							try{
								wxHttps.postMessage(accessToken, strJson1, "application/json");
							}catch(Exception e){
								exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
								exuser.setErrorInfo(e.getMessage());
							}
						}
					}
				}
				if(ValidateUtil.isEmpty(exuser.getWeChat())){
					exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
					exuser.setErrorInfo("该人员的unionID 与 微信公众号对应不上");
				}
				resultUserList.add(exuser);
			}
		}else if(WxMessageType.TEXT.equals(msgtype)){
			String jsonData = getTextJsonData(msg.getText());
			resultUserList = sendByJsonDataWithUnionID(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.IMAGE.equals(msgtype) ||
				 WxMessageType.VOICE.equals(msgtype) ||
				 WxMessageType.VIDEO.equals(msgtype)){
			List<String> media_ids = getMediaIds(accessToken, msg.getMgid(), msgtype);
			for(String media_id:media_ids){
				String jsonData = getMediaJsonData(msgtype, media_id);
				resultUserList = sendByJsonDataWithUnionID(userList, openIds, accessToken, jsonData);
			}
		}else if(WxMessageType.NEWS.equals(msgtype)){
			String jsonData = msg.getJsonData();
			if(ValidateUtil.isEmpty(jsonData)){
				jsonData = getNewsJsonData(msg.getUrl(),msg.getPicurl(),msg.getTitle(),msg.getDescription());
			}
			resultUserList = sendByJsonDataWithUnionID(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.MUSIC.equals(msgtype)){
			String jsonData = msg.getJsonData();
			resultUserList = sendByJsonDataWithUnionID(userList, openIds, accessToken, jsonData);
		}else if(WxMessageType.WXCARD.equals(msgtype)){
			String jsonData = msg.getJsonData();
			resultUserList = sendByJsonDataWithUnionID(userList, openIds, accessToken, jsonData);
		}
		return resultUserList;
	}
	
	List<TMUser> sendByJsonData(List<TMUser> userList,Set<String> openIds, String accessToken, String jsonData) throws Exception{
		List<TMUser> resultUserList = new ArrayList<>();
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		for(TMUser user:userList){
			TMUser exuser = new TMUser();
			exuser.setAppId(user.getAppId());
			exuser.setUserId(user.getUserId());
			exuser.setSendSign(user.getSendSign());
			for(String openId:openIds){
				if(openId.equals(user.getWeChat())){
					exuser.setWeChat(openId);
					String strJson = getJsonStrByJsonData(openId, jsonData);
					try{
						wxHttps.postMessage(accessToken, strJson, "application/json");
					}catch(Exception e){
						exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
						exuser.setErrorInfo(e.getMessage());
					}
				}
			}
			if(ValidateUtil.isEmpty(exuser.getWeChat())){
				exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
				exuser.setErrorInfo("该人员的 openID 与 微信公众号对应不上");
			}
			resultUserList.add(exuser);
		}
		return resultUserList;
	}
	
	List<TMUser> sendByJsonDataWithUnionID(List<TMUser> userList,Set<String> openIds, String accessToken, String jsonData) throws Exception{
		List<TMUser> resultUserList = new ArrayList<>();
		WxHttpsSendUtil wxHttps = WxHttpsSendUtil.getInstance();
		for(TMUser user:userList){
			TMUser exuser = new TMUser();
			exuser.setAppId(user.getAppId());
			exuser.setUserId(user.getUserId());
			exuser.setSendSign(user.getSendSign());
			for(String openId:openIds){
				JSONObject userinfo =JSON.parseObject(wxHttps.getUserInfo(accessToken, openId));
				if(userinfo.getString("UnionID")!=null && userinfo.getString("UnionID").equals(user.getWeChat())){
					exuser.setWeChat(openId);
					String strJson = getJsonStrByJsonData(openId, jsonData);
					try{
						wxHttps.postMessage(accessToken, strJson, "application/json");
					}catch(Exception e){
						exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
						exuser.setErrorInfo(e.getMessage());
					}
				}
			}
			if(ValidateUtil.isEmpty(exuser.getWeChat())){
				exuser.setSendSign(IMessageConstant.MSG_STATE_SEND_FAIL);
				exuser.setErrorInfo("该人员的 unionID 与 微信公众号对应不上");
			}
			resultUserList.add(exuser);
		}
		return resultUserList;
	}
}
